package com.dianpingmedia.simulate.controller;

import com.alibaba.fastjson.JSON;
import com.dianpingmedia.common.ErrorCode;
import com.dianpingmedia.common.NoticeUtil;
import com.dianpingmedia.common.utils.HttpRequest;
import com.dianpingmedia.common.utils.MiscUtil;
import com.dianpingmedia.simulate.annotation.DspId;
import com.dianpingmedia.simulate.annotation.Strategy;
import com.dianpingmedia.simulate.configuration.SimulateConfiguration;
import com.dianpingmedia.simulate.model.DPMaterialEntity;
import com.dianpingmedia.simulate.model.DPPlanEntity;
import com.dianpingmedia.simulate.model.SimulatePlanEntity;
import com.dianpingmedia.simulate.service.SimulateService;
import com.google.gson.Gson;
import net.logstash.logback.encoder.org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

import static com.dianpingmedia.simulate.controller.SimulateController.BASE_CODE;

@Component
public class AbstractController implements ApplicationListener<ContextRefreshedEvent> {
    @Value("${server.port}")
    protected int port = 8089;
    protected Logger LOGGER = LoggerFactory.getLogger(this.getClass().getSimpleName());
    protected String IP_ADDRESS = "http://" + getIpAddress() + ":" + port + "/";
    protected static Gson GSON = new Gson();

    @Autowired
    SimulateService simulateService;

    @Autowired
    NoticeUtil noticeUtil;

    public static String toJson(Object t) {
        try {
            return GSON.toJson(t);
        } catch (Exception e) {
        }
        return null;
    }

    @Autowired
    SimulateConfiguration configuration;

    private static String getIpAddress() {
        try {
            Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip = null;
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                if (netInterface.isLoopback() || netInterface.isVirtual() || !netInterface.isUp()) {
                    continue;
                } else {
                    Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        ip = addresses.nextElement();
                        if (ip != null && ip instanceof Inet4Address) {
                            return ip.getHostAddress();
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    private Map<String, Object> beansWithAnnotation;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        beansWithAnnotation = contextRefreshedEvent.getApplicationContext().getBeansWithAnnotation(Strategy.class);
    }

    /**
     * 推送转发
     *
     * @param request
     * @return
     */
    protected SimulatePlanEntity.Response transmitTo(SimulatePlanEntity.Request request) {
        SimulatePlanEntity.Response response = new SimulatePlanEntity.Response();
        for (Map.Entry<String, Object> entry : beansWithAnnotation.entrySet()) {
            Method[] methods = entry.getValue().getClass().getDeclaredMethods();
            for (Method method : methods) {
                LOGGER.info(method.getName() + ":" + method.isAnnotationPresent(DspId.class));
                if (method.isAnnotationPresent(DspId.class)) {
                    DspId dspId = method.getAnnotation(DspId.class);
                    if (dspId.value() == request.getDspId()) {
                        try {
                            DPPlanEntity.Request dpReq = convert(request);
                            String suffix = String.valueOf(method.invoke(entry.getValue(), dpReq));
                            return post(dpReq, suffix);
                        } catch (IllegalAccessException | InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        response.setMessage("NO SUPPORT THIS DSPID");
        response.setCode(BASE_CODE + ErrorCode.RESPONSE_NOT_OK.getValue());
        return response;
    }


    /**
     * 将模拟的广告计划实体转换成点屏的广告计划实体
     *
     * @param request
     * @return
     */
    private DPPlanEntity.Request convert(SimulatePlanEntity.Request request) {
        DPPlanEntity.Request req = new DPPlanEntity.Request();
        req.setId(request.getId());
        req.setAdvertiser(request.getAdvertiser());
        req.setAdvertiserId(request.getAdvertiserId());
        req.setBeginDate(request.getBeginDate());
        req.setName(request.getName());
        req.setEndDate(request.getEndDate());
        List<String> certificateIds = request.getCertificateIds();
        if (certificateIds != null && certificateIds.size() > 0) {
            List<DPMaterialEntity> entities = simulateService.queryMaterial(request.getCertificateIds());
            req.setCertificateList(entities);
        }else{
            req.setCertificateList(new ArrayList<DPMaterialEntity>());
        }
        List<DPMaterialEntity> entities = simulateService.queryMaterial(request.getMaterialIds());
        req.setMaterialList(entities);
        req.setPositionList(request.getPositionIds());
        return req;
    }


    /**
     * @param request 广告计划实体
     * @param suffix  接口后缀
     * @return
     */
    private SimulatePlanEntity.Response post(DPPlanEntity.Request request, String suffix) {
        String url = configuration.getDp_planentry_url() + suffix;
        String json = HttpRequest.doPost(url, MiscUtil.obj2Map(request));
        if (!StringUtils.isEmpty(json)) {
            return JSON.parseObject(json, SimulatePlanEntity.Response.class);
        }
        SimulatePlanEntity.Response response = new SimulatePlanEntity.Response();
        LOGGER.info("post " + url + ": \nrequest:" + toJson(request) + " \nreturn :" + json);
        response.setCode(BASE_CODE+ErrorCode.RESPONSE_NOT_OK.getValue());
        response.setMessage("post " + url + " return null");
        return response;
    }


//    protected void log(String request, String response, String uri, Integer returnCode, Integer type) {
//        simulateService.recordNotes(new SimulateNotes().setOccurredTime(SmlUtils.convert(System.currentTimeMillis()))
//                .setRequest(request)
//                .setResponse(response)
//                .setType(type)
//                .setUri(uri)
//                .setReturnCode(returnCode));
//    }


}
